Дано кубическое
уравнение
ax3 + bx2 + cx
+ d = 0 (a ≠ 0)
Известно, что у
этого уравнения ровно один корень. Найдите его.
Вход. Четыре целых числа a,
b, c, d (−1000 ≤
a, b, c, d ≤ 1000).
Выход. Выведите единственный корень уравнения с точностью не
менее 6 десятичных знаков.
Пример
входа |
Пример
выхода |
-1 -6 -12 -7 |
-1.0000000111 |
бинарный
поиск
Локализируем
корень равнения f(x) = 0. Для этого
найдем такое r, что f(-r) * f(r) < 0. Например, инициализировав r = 1, будем на каждом шаге увеличивать r в два раза пока не будет выполняться неравенство f(-r) * f(r) < 0. Таким образом будем перебирвать интервалы [-1; 1], [-2; 2], [-4; 4],
[-8; 8], …. пока не найдем
интервал в котором лежит корень уравнения.
Положим l = -r.
Далее на промежутке [l; r] при помощи бинарного поиска (деления
отрезка пополам) ищем корень.
Объявим
константу епсилон.
.
#define EPS 1e-12
Объявим функцию, вычисляющую
кубический многочлен.
double f(double
x)
{
return
a*x*x*x + b*x*x + c*x + d;
}
Основная часть
программы. Читаем входные данные.
scanf("%lf %lf %lf %lf",&a,&b,&c,&d);
Находим границы [l; r], в которых лежит
искомый корень. Положим изначально r
= 1. Будем последовательно увеличивать r
в два раза, пока искомый корень не будет находиться в промежутке [-r; r]
(для этого необходимо, чтобы функция f(x)
принимала противоположные по знаку значения на концах интервала). После чего
положим l = -r.
r = 1;
while(f(r) * f(-r) >= 0) r *= 2;
l = -r;
При помощи бинарного поиска ищем
корень уравнения f(x) = 0 на
промежутке [l; r].
while (r - l > EPS)
{
x = (l + r) / 2;
if (f(x) *
f(r) > 0) r = x; else l = x;
}
Выводим ответ.
printf("%.8lf\n",l);
Java реализация
import java.util.*;
public class Main
{
static double a, b, c, d;
static double f(double x)
{
return a*x*x*x + b*x*x + c*x + d;
}
public static void main(String[] args)
{
Scanner con = new
Scanner(System.in);
a = con.nextDouble();
b = con.nextDouble();
c = con.nextDouble();
d = con.nextDouble();
double right = 1;
while(f(right) * f(-right) >= 0) right *= 2;
double left = -right;
while (right - left > 1e-6)
{
double middle = (left + right) / 2;
if (f(middle) * f(right) > 0) right = middle;
else left = middle;
}
System.out.println(left);
con.close();
}
}